﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using blackhouse.BlackApart.Data;
using System.Web.Caching;
using System.Web;

namespace blackhouse.BlackApart.Data.Caching {
    public class CachedReservationDataAccess : IReservationDataAccess {

        #region Fields

        private IReservationDataAccess decoratedDataAccess;
        private NemoCache cache;

        #endregion

        #region Constructors

        public CachedReservationDataAccess(IReservationDataAccess decoratedDataAccess, string connectionStringToDecoretedDb) {
            this.decoratedDataAccess = decoratedDataAccess;
            this.cache = new NemoCache(TimeSpan.FromMinutes(2), connectionStringToDecoretedDb);
        }

        #endregion

        #region Methods

        public bool UpdateWebReservation(int reservationId, DateTime arrivalDate, DateTime departureDate, double finalPrice, double price, float Rabat, bool vatInvoice, string comments, int clientId, int paymentTypeId) {
            return this.decoratedDataAccess.UpdateWebReservation(reservationId, arrivalDate, departureDate, finalPrice, price, Rabat, vatInvoice, comments, clientId, paymentTypeId);
        }

        public WebReservationData GetWebReservation(int reservationId, string language) {
            return this.decoratedDataAccess.GetWebReservation(reservationId, language);
        }

        public WebReservationData GetWebReservation(Guid reservationGuid, string language) {
            return this.decoratedDataAccess.GetWebReservation(reservationGuid, language);
        }

        public WebReservationData GetWebReservation(string reservationNumber, string language) {
            return this.decoratedDataAccess.GetWebReservation(reservationNumber, language);
        }

        public ApartmentWebReservationData[] GetApartmentsWebReservation(int reservationId) {
            return this.decoratedDataAccess.GetApartmentsWebReservation(reservationId);
        }

        public ReservationPriceRabatData[] GetRabatsWebReservation(int reservationId, string language) {
            return this.decoratedDataAccess.GetRabatsWebReservation(reservationId, language);
        }

        public WebReservationData[] FindReservationForInterviewer() {
            cache.Reset();
            cache.SetDependencyTables("T51");
            WebReservationData[] data = cache.GetData<WebReservationData[]>();
            if (data == null) {
                data = this.decoratedDataAccess.FindReservationForInterviewer();
                cache.SetCaching(data);
            }
            return data;
        }

        //public bool RemoveReservation(int reservationId) {
        //    cache.TouchTimes();
        //    return this.decoratedDataAccess.RemoveReservation(reservationId);
        //}

        //public int SaveReservation(int reservationId, int apartmentId, int numberOfPeople, DateTime startDate, DateTime endDate) {
        //    return this.SaveReservation(reservationId, apartmentId, 0, 0, 0, numberOfPeople, startDate, endDate);
        //}

        //public int SaveReservation(int reservationId, int apartmentId, double price, double priceWithoutRabat, float rabat, int numberOfPeople, DateTime startDate, DateTime endDate) {
        //    cache.TouchTimes();
        //    return decoratedDataAccess.SaveReservation(reservationId, apartmentId, price, priceWithoutRabat, rabat, numberOfPeople, startDate, endDate);
        //}

        public WebReservationSaveData AddWebReservation(DateTime arrivalDate, DateTime departureDate, double priceWithRabat, double price, float rabat) {
            return this.decoratedDataAccess.AddWebReservation(arrivalDate, departureDate, priceWithRabat, price, rabat);
        }

        public int AddApartmentToReservation(int reservationId, int apartmentId, int forPeoples) {
            return this.decoratedDataAccess.AddApartmentToReservation(reservationId, apartmentId, forPeoples);
        }

        public int AddRabatToReservation(int reservationId, string rabatKey, float rabatValue) {
            return this.decoratedDataAccess.AddRabatToReservation(reservationId, rabatKey, rabatValue);
        }

        public void RollbackWebReservation(int reservationId) {
            this.decoratedDataAccess.RollbackWebReservation(reservationId);
        }

        //public ReservationData[] GetReservations(int apartmentId, DateTime startDate, DateTime endDate) {
        //    cache.Reset();
        //    cache.SetDependencyTables("T43");
        //    cache.SetParameters(apartmentId, startDate, endDate);
        //    cache.SetKey("GetReservations");
        //    ReservationData[] data = cache.GetData<ReservationData[]>();
        //    if (data == null) {
        //        data = this.decoratedDataAccess.GetReservations(apartmentId, startDate, endDate);
        //        cache.SetCaching(data);
        //    }
        //    return data;
        //}

        public ClientData GetClient(int clientId) {
            cache.Reset();
            cache.SetDependencyTables("T34");
            cache.SetParameters(clientId);
            cache.SetKey("GetClient");
            ClientData data = cache.GetData<ClientData>();
            if (data.Id == 0) {
                data = this.decoratedDataAccess.GetClient(clientId);
                cache.SetCaching(data);
            }
            return data;
        }

        public ClientData GetClientByEmail(string email) {
            cache.Reset();
            cache.SetDependencyTables("T34");
            cache.SetParameters(email);
            cache.SetKey("GetClientByEmail");
            ClientData data = cache.GetData<ClientData>();
            if (data.Id == 0) {
                data = this.decoratedDataAccess.GetClientByEmail(email);
                cache.SetCaching(data);
            }
            return data;
        }

        public int SaveClient(string eMail, string phoneNumber, string personTitle, string firstName, string lastName, string language, string currency) {
            this.cache.TouchTimes();
            return this.decoratedDataAccess.SaveClient(eMail, phoneNumber, personTitle, firstName, lastName, language, currency);
        }

        //public int SavePaymentType(int id, string key, bool waitForCash) {
        //    this.cache.TouchTimes();
        //    return this.decoratedDataAccess.SavePaymentType(id, key, waitForCash);
        //}

        //public int AddReservationHeader(int clientId, double totalPrice, double totalPriceWithoutRabat, float rabat, bool vatInvoice, int paymentTypeId, string reservationTypeId) {
        //    this.cache.TouchTimes();
        //    return this.decoratedDataAccess.AddReservationHeader(clientId, totalPrice, totalPriceWithoutRabat, rabat, vatInvoice, paymentTypeId, reservationTypeId);
        //}

        //public bool JoinReservationHeader(int userReservationId, int apartmentReservationId) {
        //    this.cache.TouchTimes();
        //    return this.decoratedDataAccess.JoinReservationHeader(userReservationId, apartmentReservationId);
        //}

        //public ReservationHeaderData GetReservationHeader(int reservationId, string language) {
        //    cache.Reset();
        //    cache.SetDependencyTables("T51", "T51_T43", "T43", "T130", "T137");
        //    cache.SetParameters(reservationId, language);
        //    cache.SetKey("GetReservationHeader");
        //    ReservationHeaderData data = cache.GetData<ReservationHeaderData>();
        //    if (data.Id == 0) {
        //        data = this.decoratedDataAccess.GetReservationHeader(reservationId, language);
        //        cache.SetCaching(data);
        //    }
        //    return data;
        //}

        //public ReservationHeaderData GetReservationHeader(string reservationNumber, string language) {
        //    cache.Reset();
        //    cache.SetDependencyTables("T51", "T51_T43", "T43", "T130", "T137");
        //    cache.SetParameters(reservationNumber, language);
        //    cache.SetKey("GetReservationHeader");
        //    ReservationHeaderData data = cache.GetData<ReservationHeaderData>();
        //    if (data.Id == 0) {
        //        data = this.decoratedDataAccess.GetReservationHeader(reservationNumber, language);
        //        cache.SetCaching(data);
        //    }
        //    return data;
        //}

        public PaymentData GetPaymentType(int paymentTypeId, string language) {
            cache.Reset();
            cache.SetDependencyTables("T40");
            cache.SetParameters(paymentTypeId, language);
            cache.SetKey("GetPaymentType");
            PaymentData data = cache.GetData<PaymentData>();
            if (data.PaymentTypeId == 0) {
                data = this.decoratedDataAccess.GetPaymentType(paymentTypeId, language);
                cache.SetCaching(data);
            }
            return data;
        }

        public PaymentData[] GetWebPaymentTypes(string language) {
            cache.Reset();
            cache.SetDependencyTables("T40");
            cache.SetParameters(language);
            cache.SetKey("GetWebPaymentTypes");
            PaymentData[] data = cache.GetData<PaymentData[]>();
            if (data == null) {
                data = this.decoratedDataAccess.GetWebPaymentTypes(language);
                cache.SetCaching(data);
            }
            return data;
        }

        //public ReservationData[] GetReservationsByHeader(int reservationId) {
        //    cache.Reset();
        //    cache.SetDependencyTables("T51", "T51_T43", "T43");
        //    cache.SetParameters(reservationId);
        //    cache.SetKey("GetReservationsByHeader");
        //    ReservationData[] data = cache.GetData<ReservationData[]>();
        //    if (data == null) {
        //        data = this.decoratedDataAccess.GetReservationsByHeader(reservationId);
        //        cache.SetCaching(data);
        //    }
        //    return data;
        //}

        //public void AddMailToSend(int reservationId) {
        //    this.decoratedDataAccess.AddMailToSend(reservationId);
        //}

        public bool ChangeReservationStatus(int reservationId, string newStatusKey) {
            cache.TouchTimes();
            return this.decoratedDataAccess.ChangeReservationStatus(reservationId, newStatusKey);
        }

        public Dictionary<DateTime, int> GetAvabilityOfApartmentType(int groupId, DateTime fromDay, DateTime toDay) {
            cache.Reset();
            cache.SetDependencyTables("T43");
            cache.SetParameters(groupId, fromDay, toDay);
            cache.SetKey("GetAvabilityOfApartmentType");
            Dictionary<DateTime, int> data = cache.GetData<Dictionary<DateTime, int>>();
            if (data == null) {
                data = this.decoratedDataAccess.GetAvabilityOfApartmentType(groupId, fromDay, toDay);
                cache.SetCaching(data);
            }
            return data;
        }

        #endregion

    }
}
